package com.mxpio.erp.workshop.controller;

import java.io.UnsupportedEncodingException;
import java.util.List;

import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.mxpio.erp.common.enums.OrderEnums;
import com.mxpio.erp.common.enums.OrderStatusEnums;
import com.mxpio.erp.common.jpa.model.Order;
import com.mxpio.erp.common.order.policy.OrderContext;
import com.mxpio.erp.common.order.service.OrderService;
import com.mxpio.erp.common.vo.OrderExcuteVo;
import com.mxpio.erp.common.workshop.entity.ManufactureOrder;
import com.mxpio.erp.common.workshop.entity.ManufactureOrderItem;
import com.mxpio.erp.common.workshop.service.ManufactureOrderItemService;
import com.mxpio.erp.common.workshop.service.ManufactureOrderService;
import com.mxpio.erp.workshop.policy.impl.DefaultExecuteMoPolicy;
import com.mxpio.erp.workshop.policy.impl.DefaultPickingMoPolicy;
import com.mxpio.erp.workshop.policy.impl.ManufactureOrderSavePolicy;
import com.mxpioframework.common.vo.Result;
import com.mxpioframework.jpa.query.Criteria;
import com.mxpioframework.jpa.query.Operator;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;

@Tag(name = "ManufactureOrderController", description = "生产订单接口")
@RestController
@RequestMapping("/erp/workshop/mo/")
public class ManufactureOrderController {

	@Autowired
	private ManufactureOrderService manufactureOrderService;
	
	@Autowired
	private ManufactureOrderItemService manufactureOrderItemService;
	
	@Autowired
	private OrderService bizOrderService;
	
	@Autowired
    private ManufactureOrderSavePolicy manufactureOrderSavePolicy;
	
	@GetMapping("list")
    @Operation(summary = "生产订单列表", description = "获取生产订单列表（无分页）", method = "GET")
    public Result<List<ManufactureOrder>> list(@Parameter(description="查询参数") Criteria criteria) throws UnsupportedEncodingException {
        List<ManufactureOrder> manufactureOrders = manufactureOrderService.list(ManufactureOrder.class, criteria);
        return Result.OK(manufactureOrders);
    }

    @GetMapping("page")
    @Operation(summary = "生产订单列表", description = "获取生产订单列表（分页）", method = "GET")
    public Result<Page<ManufactureOrder>> page(@Parameter(description="查询参数") Criteria criteria, @Parameter(description="每页条数")Integer pageSize, @Parameter(description="页号")Integer pageNo) throws UnsupportedEncodingException {
        Pageable page = PageRequest.of(pageNo-1, pageSize);
        Page<ManufactureOrder> pageResult = manufactureOrderService.listPage(ManufactureOrder.class, page, criteria);
        manufactureOrderService.handleManufactureOrderQuantity(pageResult.getContent(), OrderEnums.AccessType.IN.getCode());
        return Result.OK(pageResult);
    }

    @GetMapping("list/{bizNo}")
    @Operation(summary = "根据bizNo获取生产订单", description = "根据bizNo获取生产订单", method = "GET")
    public Result<ManufactureOrder> getById(@Parameter(description="业务单号") @PathVariable(name = "bizNo", required = true) String bizNo) {
        ManufactureOrder manufactureOrder = manufactureOrderService.getById(ManufactureOrder.class, bizNo);
        return Result.OK(manufactureOrder);
    }

    @RequestMapping("save")
    @Operation(summary = "保存生产订单", description = "保存生产订单")
    public Result<ManufactureOrder> save(@RequestBody ManufactureOrder manufactureOrder) {
        manufactureOrderService.save(manufactureOrder,manufactureOrderSavePolicy);
        Criteria c = Criteria.create().addCriterion("bizNo", Operator.EQ, manufactureOrder.getBizNo());
        manufactureOrder.setManufactureOrderItems(manufactureOrderItemService.list(ManufactureOrderItem.class, c));
        return Result.OK(manufactureOrder);
    }
    
    @RequestMapping("excute/{bizNo}")
    @Operation(summary = "订单报完工", description = "订单报完工")
    public Result<Object> excute(@PathVariable(name = "bizNo", required = true) String bizNo, 
    		@RequestBody OrderExcuteVo orderExcuteVo) {
    	ManufactureOrder order = manufactureOrderService.getById(ManufactureOrder.class, bizNo);
    	
    	OrderContext context = bizOrderService.execute(order, new DefaultExecuteMoPolicy(orderExcuteVo.getLines()));
    	if(CollectionUtils.isEmpty(context.getErrors())) {
    		return Result.OK();
    	}else {
    		return Result.error(context.getErrors().get(0));
    	}
    }
    
    @RequestMapping("excute/{type}/{bizNo}")
    @Operation(summary = "领/退/补料", description = "领/退/补料")
    public Result<Object> excute(@PathVariable(name = "bizNo", required = true) String bizNo, 
    		@PathVariable(name = "type", required = true) @Parameter(description = "-1:退料；2：补料；1：领料") String type,
    		@RequestBody OrderExcuteVo orderExcuteVo) {
    	ManufactureOrder order = manufactureOrderService.getById(ManufactureOrder.class, bizNo);
    	
    	OrderContext context = bizOrderService.execute(order, new DefaultPickingMoPolicy(orderExcuteVo.getLines(), type));
    	if(CollectionUtils.isEmpty(context.getErrors())) {
    		return Result.OK();
    	}else {
    		return Result.error(context.getErrors().get(0));
    	}
    }

    @DeleteMapping("remove/{bizNos}")
    @Operation(summary = "根据bizNo删除生产订单", description = "删除生产订单", method = "DELETE")
    @Transactional(readOnly = false)
    public Result<ManufactureOrder> remove(@Parameter(description="业务单号，多个单号用英文逗号分隔") @PathVariable(name = "bizNos", required = true) String bizNos) {
        String[] bizNo = bizNos.split(",");
        for(String key : bizNo){
        	Criteria c = Criteria.create().addCriterion("bizNo", Operator.EQ, key);
        	manufactureOrderItemService.removeBatch(ManufactureOrderItem.class, c);
            manufactureOrderService.delete(ManufactureOrder.class, key);
        }
        return Result.OK();
    }
    
    @PutMapping("submit/{bizNo}")
    @Operation(summary = "提交生产订单", description = "提交生产订单", method = "PUT")
    public Result<? extends Order> submit(@Parameter(description="业务单号") @PathVariable(name = "bizNo", required = true) String bizNo) {
    	ManufactureOrder so = manufactureOrderService.getById(ManufactureOrder.class,bizNo);
    	if(so.getBpmnStatus().equals(OrderStatusEnums.BpmnStatus.CREATE.getStatusCode())){
    		return bizOrderService.updateBpmnStatus(so, OrderStatusEnums.BpmnStatus.AUDITING);
    	}else {
    		return Result.error("非开立状态不可提交");
		}
    }

    @PutMapping("audit/{bizNo}")
    @Operation(summary = "审核生产订单", description = "审核生产订单", method = "PUT")
    public Result<? extends Order> audit(@Parameter(description="业务单号") @PathVariable(name = "bizNo", required = true) String bizNo) {
    	ManufactureOrder so = manufactureOrderService.getById(ManufactureOrder.class,bizNo);
    	if(so.getBpmnStatus().equals(OrderStatusEnums.BpmnStatus.AUDITING.getStatusCode())){
    		return bizOrderService.updateBpmnStatus(so, OrderStatusEnums.BpmnStatus.AUDITED);
    	}else {
    		return Result.error("非审核中状态不可审核");
		}
    }

    @PutMapping("abandon/{bizNo}")
    @Operation(summary = "弃审生产订单", description = "弃审生产订单", method = "PUT")
    public Result<? extends Order> abandon(@Parameter(description="业务单号") @PathVariable(name = "bizNo", required = true) String bizNo) {
    	ManufactureOrder mo = manufactureOrderService.getById(ManufactureOrder.class,bizNo);
    	if(mo.getBpmnStatus().equals(OrderStatusEnums.BpmnStatus.AUDITING.getStatusCode())||mo.getBpmnStatus().equals(OrderStatusEnums.BpmnStatus.AUDITED.getStatusCode())){
    		return bizOrderService.updateBpmnStatus(mo, OrderStatusEnums.BpmnStatus.CREATE);
    	}else{
    		return Result.error("非审核中、已审核状态不可审核");
    	}
    }

    @PutMapping("export/{bizNos}")
    @Operation(summary = "导出生产订单", description = "导出生产订单", method = "PUT")
    public Result<ManufactureOrder> export(@Parameter(description="业务单号，多个单号用英文逗号分隔") @PathVariable(name = "bizNos", required = true) String bizNos) {
        //TODO:导出逻辑
        return Result.OK();
    }

    @PutMapping("open/{bizNo}")
    @Operation(summary = "打开生产订单", description = "打开生产订单", method = "PUT")
    public Result<? extends Order> open(@Parameter(description="业务单号") @PathVariable(name = "bizNo", required = true) String bizNo) {
    	ManufactureOrder mo = manufactureOrderService.getById(ManufactureOrder.class,bizNo);
    	return bizOrderService.updateCloseStatus(mo, OrderStatusEnums.CloseStatus.OPEN);
    }

    @PutMapping("close/{bizNo}")
    @Operation(summary = "关闭生产订单", description = "关闭生产订单", method = "PUT")
    public Result<? extends Order> close(@Parameter(description="业务单号") @PathVariable(name = "bizNo", required = true) String bizNo) {
    	ManufactureOrder mo = manufactureOrderService.getById(ManufactureOrder.class,bizNo);
    	return bizOrderService.updateCloseStatus(mo, OrderStatusEnums.CloseStatus.CLOSED);
    }
    
    @PutMapping("order/{bizNo}")
    @Operation(summary = "下达生产订单", description = "下达生产订单", method = "PUT")
    public Result<? extends Order> order(@Parameter(description="业务单号") @PathVariable(name = "bizNo", required = true) String bizNo) {
    	ManufactureOrder mo = manufactureOrderService.getById(ManufactureOrder.class,bizNo);
    	if(OrderStatusEnums.OrderStatus.PLAN.getStatusCode().equals(mo.getOrderStatus())){
    		return bizOrderService.updateOrderStatus(mo, OrderStatusEnums.OrderStatus.ORDERED);
    	}else{
    		return Result.error("非计划状态不可下达");
    	}
    }
    
    @PutMapping("clear/{bizNo}")
    @Operation(summary = "结算生产订单", description = "结算生产订单", method = "PUT")
    public Result<? extends Order> clear(@Parameter(description="业务单号") @PathVariable(name = "bizNo", required = true) String bizNo) {
    	ManufactureOrder mo = manufactureOrderService.getById(ManufactureOrder.class,bizNo);
    	if(OrderStatusEnums.OrderStatus.FINISHED.getStatusCode().equals(mo.getOrderStatus())){
    		return bizOrderService.updateOrderStatus(mo, OrderStatusEnums.OrderStatus.CLEARED);
    	}else{
    		return Result.error("非完成状态不可结算");
    	}
    }
    
    @PutMapping("finish/{bizNo}")
    @Operation(summary = "生产订单完工", description = "生产订单完工", method = "PUT")
    public Result<? extends Order> finish(@Parameter(description="业务单号") @PathVariable(name = "bizNo", required = true) String bizNo) {
    	ManufactureOrder mo = manufactureOrderService.getById(ManufactureOrder.class,bizNo);
    	if(OrderStatusEnums.OrderStatus.PROCESSING.getStatusCode().equals(mo.getOrderStatus())){
    		return bizOrderService.updateOrderStatus(mo, OrderStatusEnums.OrderStatus.FINISHED);
    	}else{
    		return Result.error("非执行状态不可报完工");
    	}
    }
}
